#include <func.h>
#include "md5.h"

int PUTS_handle(char* username, int netfd, const char* path, const char* md5){
    
    train_t train;//创建小火车
    memset(&train,0,sizeof(train));
    
    
     ////查询数据库，判断目标路径是否存在
   
    //连接数据库
    MYSQL * mysql = mysql_init(NULL); // 为mysql连接分配内存（线程不安全）
    MYSQL * ret = mysql_real_connect(mysql,"localhost","root","2891","netdisk",0,NULL,0);//密码和库名需要根据情况更改
    if(ret == NULL){
        fprintf(stderr,"mysql connect error:%s\n", mysql_error(mysql));
        return -1;
    }
    char sql[1024] = {0};
    ////查询对应路径id


    //sprintf(sql,"select * from fileInfo where user=%s and type=d and tomb=0;"
    //        ,username);//添加preid
    //int qret = mysql_query(mysql,sql);
    //if(qret != 0){
    //    fprintf(stderr,"sql error:%s\n", mysql_error(mysql));
    //    return -1;
    //}
    //MYSQL_RES *result = mysql_store_result(mysql); //取出读取的结果
    //printf("total rows = %lu\n", mysql_num_rows(result));
    //
    ////如果不存在，通知客户端，退出
    ////if(mysql_num_rows(result) != 1){
    ////    //TO DO 错误处理
    ////    train_t train;
    ////    train.length = -1;
    ////    memcpy(train.data,"ERROR:NO PATH!",14);
    ////    send(netfd,&train,sizeof(train_t),MSG_NOSIGNAL);
    ////    SYSLOG(username,"PUTS",path,"FAIL:NO PATH TO PUTS!");
    ////    return -1;
    ////}
    ////如果存在，通知客户端，继续
    //train_t train;
    //train.length = 0;
    //memcpy(train.data,"ALLOW PUTS!",11);
    //send(netfd,&train,sizeof(train_t),MSG_NOSIGNAL);

    ////接收md5码
    //char md5[32+1];
    //recvn(netfd,&train.length,sizeof(train.length));
    //recvn(netfd,md5,train.length);
    
    //判断文件是否已存在
    sprintf(sql,"select * from fileInfo where md5=%s;",md5);//直接用md5查
    int qret = mysql_query(mysql,sql);
    if(qret != 0){
        fprintf(stderr,"sql error:%s\n", mysql_error(mysql));
        return -1;
    }
    MYSQL_RES* result = mysql_store_result(mysql); //取出读取的结果
    printf("total rows = %lu\n", mysql_num_rows(result));
    //修稿查询方式
      //查找路径匹配的那一项（逐级查找）
    MYSQL_ROW row;
    char path_sql[1024];
    bool is_fileExist = 0;
    int pre_id;
    while((row = mysql_fetch_row(result)) != NULL){
        memset(path_sql,0,sizeof(path_sql));
        MYSQL_ROW row_preid;
        char sql_preid[1024] = {0};
        sprintf(sql_preid,"select * from fileInfo where id = %s;",row[3]);
        qret = mysql_query(mysql,sql_preid);
        if(qret != 0){
            fprintf(stderr,"sql error:%s\n", mysql_error(mysql));
            return -1;
        }
        MYSQL_RES *result_preid = mysql_store_result(mysql); //取出读取的结果
        row_preid = mysql_fetch_row(result_preid);
        char tmp[1024];
        strcpy(tmp,path_sql);
        sprintf(path_sql,"%s",row_preid[1]);  //存在冗余代码
        do{
            memset(sql_preid,0,sizeof(sql_preid));
            sprintf(sql_preid,"select * from fileInfo where id = %s;",row_preid[3]);
            qret = mysql_query(mysql,sql_preid);
            if(qret != 0){
                fprintf(stderr,"sql error:%s\n", mysql_error(mysql));
                return -1;
            }
            MYSQL_RES *result_preid = mysql_store_result(mysql); //取出读取的结果
            row_preid = mysql_fetch_row(result_preid);
            strcpy(tmp,path_sql);
            sprintf(path_sql,"%s/%s",row_preid[1],tmp);

        }
        while(strcmp(row_preid[3],"-1"));
        if(strcmp(path_sql,path) == 0){
            is_fileExist = 1;
            pre_id = atoi(row[3]); //潜在风险,获取preid
        }
    }
    
    //如果文件已存在,tomb置0，通知客户端，退出
    if(is_fileExist){
        sprintf(sql,"update fileInfo set tomb=0 where user=%s pre_id=%d and type=f and md5=%s;"
                ,username,pre_id,md5);
        qret = mysql_query(mysql,sql);
        MYSQL_ROW row;
        row = mysql_fetch_row(result);
        train.length = -1;
        memcpy(train.data,"FINISH PUTS!",12);
        send(netfd,&train,sizeof(train_t),MSG_NOSIGNAL);
        SYSLOG(username,"PUTS",path,"FINISH PUTS:FILE EXIST");
        return 0;
    }
    //如果文件不存在，创建文件，通知客户端，继续
    train.length = 0;
    memcpy(train.data,"BEGIN PUTS!",11);
    send(netfd,&train,sizeof(train_t),MSG_NOSIGNAL);

    int fd = open(md5,O_RDWR|O_CREAT,0666);
    
    // 先收文件名
    char filename[1024] = {0};
    int length;
    recvn(netfd,length,sizeof(length));//收火车头
    recvn(netfd,filename,length);

    //再收文件大小
    off_t filesize = 0;
    recvn(netfd,&length,sizeof(length));
    recvn(netfd,&filesize,length);
    printf("filesize = %ld\n", filesize);

    //收文件内容
    if(filesize<100*1024*1024){
        off_t cursize = 0;
        off_t slice = filesize/10000;
        off_t lastsize = 0;//上次打印的时候文件大小
        while(1){
            char buf[4096] = {0};
            recvn(netfd,&length,sizeof(length));
            if(length != 1000){
                printf("length = %d\n", length);
            }
            if(length == 0){
                break;
            }
            recvn(netfd,buf,length);
            write(fd,buf,length);

            cursize += length;
            if(cursize - lastsize > slice){
                printf("%5.2lf%%\r",100.0*cursize/filesize);
                fflush(stdout);//将stdout缓冲区的数据刷到文件对象里面
                lastsize = cursize;
            }
        }
        close(fd);
        printf("100.00%%\n");
    }
    else{
        ftruncate(fd,filesize);
        char *p=(char*)mmap(NULL,filesize,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);
        ERROR_CHECK(p,MAP_FAILED,"mmap");
        recvn(netfd,p,filesize);
        munmap(p,filesize);
        close(fd);
        printf("100.00%%\n");
    }

    //验证收到文件内容生成的MD5码是否正确
    //真实文件名为md5
    char md5_compute[32+1];
    int ret_computeMd5 = Compute_file_md5(md5,md5_compute);
    printf("md5 = %s\nmd5_compute = %s\n",md5,md5_compute);
    if(strcmp(md5,md5_compute) == 0){
        printf("The md5 is same!\n");
        train.length = 0;
        memcpy(train.data,"SUCCESS:MD5 SAME!",17);
        send(netfd,&train,sizeof(train_t),MSG_NOSIGNAL);
        SYSLOG(username,"PUTS",path,"SUCCESS:MD5 SAME");

    }
    else{
        printf("The md5 is different!\n");
        //通知客户端上传失败
        train.length = -1;
        memcpy(train.data,"FAIL:MD5 DIFFERENT!",19);
        send(netfd,&train,sizeof(train_t),MSG_NOSIGNAL);
        SYSLOG(username,"PUTS",path,"FINISH PUTS:FILE EXIST");
        return -1;
    }


    //将新文件的信息上传至数据库（考虑同名不同md5码的情况
    memset(sql,0,sizeof(sql));
    sprintf(sql,"insert into fileInfo (name,user,pre_id,type,md5,tomb,path) values (filename,username,pre_id,'f',md5,0,NULL);");
    qret = mysql_query(mysql,sql);
    if(qret != 0){
        fprintf(stderr,"sql error:%s\n", mysql_error(mysql));
        return -1;
    }

    SYSLOG(username,"PUTS",path,"success");

    return 0;
}

